{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.core.interactiveshell import InteractiveShell\n",
    "InteractiveShell.ast_node_interactivity = \"all\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.将序列拆分为单独的变量\n",
    "\n",
    "不仅仅只是元组或列表，只要对象是可迭代的，就可以执行分解操作。 包括字符串，文件对象，迭代器和生成器。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ACME'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "50"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "91.1"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "(2012, 12, 21)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]\n",
    "\n",
    "name, shares, price, date = data\n",
    "\n",
    "name\n",
    "shares\n",
    "price\n",
    "date"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'H'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'e'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'l'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'l'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'o'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = 'Hello'\n",
    "\n",
    "a, b, c, d, e = s\n",
    "a\n",
    "b\n",
    "c\n",
    "d\n",
    "e"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "50"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "91.1"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "(2012, 12, 21)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]\n",
    "\n",
    "_, shares, price, _ = data\n",
    "\n",
    "shares\n",
    "price\n",
    "_\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.解压可迭代对象赋值给多个变量\n",
    "\n",
    "使用星号表达式：`param1, param2, *param, paramN = array`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Dave'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'dave@example.com'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['773-555-1212', '847-555-1212']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212')\n",
    "\n",
    "name, email, *phone_numbers = record\n",
    "\n",
    "name\n",
    "email\n",
    "phone_numbers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Dave'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'dave@example.com'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "record = ('Dave', 'dave@example.com')\n",
    "\n",
    "name, email, *phone_numbers = record\n",
    "\n",
    "name\n",
    "email\n",
    "phone_numbers\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Dave'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'dave@example.com'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['773-555-1212', '847-555-1212']"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'age=12'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "record = ('Dave', 'dave@example.com', '773-555-1212', '847-555-1212', \"age=12\")\n",
    "\n",
    "name, email, *phone_numbers, age = record\n",
    "\n",
    "name\n",
    "email\n",
    "phone_numbers\n",
    "age\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'nobody'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'/var/empty'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'/usr/bin/false'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['*', '-2', '-2', 'Unprivileged User']"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 星号解压语法在字符串操作的时候也会很有用，比如字符串的分割。\n",
    "\n",
    "line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'\n",
    "\n",
    "uname, *fields, homedir, sh = line.split(':')\n",
    "\n",
    "uname\n",
    "homedir\n",
    "sh\n",
    "fields"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ACME'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "2012"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 有时候，你想解压一些元素后丢弃它们，你不能简单就使用 * ， 但是你可以使用一个普通的废弃名称，比如 _ 或者 ign （ignore）\n",
    "record = ('ACME', 50, 123.45, (12, 18, 2012))\n",
    "name, *_, (*_, year) = record\n",
    "name\n",
    "year"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.保留最后 N 个元素(collections.deque)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([1, 2, 3])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "deque([2, 3, 4])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "deque([3, 4, 5])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from collections import deque\n",
    "\n",
    "# 使用 deque(maxlen=N) 构造函数会新建一个固定大小的队列。\n",
    "# 当新的元素加入并且这个队列已满的时候， 最老的元素会自动被移除掉。\n",
    "q = deque(maxlen=3)\n",
    "q.append(1)\n",
    "q.append(2)\n",
    "q.append(3)\n",
    "q\n",
    "q.append(4)\n",
    "q\n",
    "q.append(5)\n",
    "q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([1, 2, 3])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "deque([4, 1, 2, 3])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "deque([4, 1, 2])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "deque([1, 2])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如果你不设置最大队列大小，那么就会得到一个无限大小队列，你可以在队列的两端执行添加和弹出元素的操作。\n",
    "\n",
    "q = deque()\n",
    "q.append(1)\n",
    "q.append(2)\n",
    "q.append(3)\n",
    "q\n",
    "q.appendleft(4)\n",
    "q\n",
    "q.pop()\n",
    "q\n",
    "q.popleft()\n",
    "q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 4.查找最大或最小的 N 个元素\n",
    "\n",
    "heapq 模块有两个函数：nlargest() 和 nsmallest() 可以完美解决这个问题。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[42, 37, 23]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[-4, 1, 2]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import heapq\n",
    "nums = [1, 8, 2, 23,  7, -4, 18, 23, 42, 37, 2]\n",
    "heapq.nlargest(3, nums)\n",
    "heapq.nsmallest(3, nums)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'name': 'AAPL', 'shares': 50, 'price': 543.22},\n",
       " {'name': 'ACME', 'shares': 75, 'price': 115.65},\n",
       " {'name': 'IBM', 'shares': 100, 'price': 91.1}]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[{'name': 'AAPL', 'shares': 50, 'price': 543.22},\n",
       " {'name': 'ACME', 'shares': 75, 'price': 115.65},\n",
       " {'name': 'IBM', 'shares': 100, 'price': 91.1}]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import heapq\n",
    "portfolio = [\n",
    "    {'name': 'IBM', 'shares': 100, 'price': 91.1},\n",
    "    {'name': 'AAPL', 'shares': 50, 'price': 543.22},\n",
    "    {'name': 'FB', 'shares': 200, 'price': 21.09},\n",
    "    {'name': 'HPQ', 'shares': 35, 'price': 31.75},\n",
    "    {'name': 'YHOO', 'shares': 45, 'price': 16.35},\n",
    "    {'name': 'ACME', 'shares': 75, 'price': 115.65}\n",
    "]\n",
    "\n",
    "#在对每个元素进行对比的时候，会以 price 的值进行比较\n",
    "cheap = heapq.nlargest(3, portfolio, key=lambda s: s[\"price\"])\n",
    "cheap\n",
    "\n",
    "expensive = heapq.nlargest(3, portfolio, key=lambda s: s[\"price\"])\n",
    "expensive"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import heapq\n",
    "nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]\n",
    "heapq.heapify(nums)\n",
    "nums"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 6.字典中的键映射多个值\n",
    "\n",
    "可以很方便的使用 collections 模块中的 defaultdict 来构造这样的字典。 defaultdict 的一个特征是它会自动初始化每个 key 刚开始对应的值，所以你只需要关注添加元素操作了。\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "defaultdict(set, {'a': {1, 2}, 'b': {4}})"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "set()"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'a': [1, 2], 'b': [4]}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "d = defaultdict(list)\n",
    "d['a'].append(1)\n",
    "d['a'].append(2)\n",
    "d['b'].append(4)\n",
    "\n",
    "d = defaultdict(set)\n",
    "d['a'].add(1)\n",
    "d['a'].add(2)\n",
    "d['b'].add(4)\n",
    "\n",
    "d\n",
    "\n",
    "# efaultdict 会自动为将要访问的键（就算目前字典中并不存在这样的键）创建映射实体\n",
    "d['c']\n",
    "\n",
    "# 如果你并不需要这样的特性，你可以在一个普通的字典上使用 setdefault() 方法来代替\n",
    "d = {} # 一个普通的字典\n",
    "d.setdefault('a', []).append(1)\n",
    "d.setdefault('a', []).append(2)\n",
    "d.setdefault('b', []).append(4)\n",
    "d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 7.字典排序\n",
    "\n",
    "为了能控制一个字典中元素的顺序，你可以使用 collections 模块中的 OrderedDict 类。 在迭代操作的时候它会保持元素被插入时的顺序。\n",
    "\n",
    "OrderedDict 内部维护着一个根据键插入顺序排序的双向链表。每次当一个新的元素插入进来的时候， 它会被放到链表的尾部。对于一个已经存在的键的重复赋值不会改变键的顺序。\n",
    "\n",
    "需要注意的是，一个 OrderedDict 的大小是一个普通字典的两倍，因为它内部维护着另外一个链表。 所以如果你要构建一个需要大量 OrderedDict 实例的数据结构的时候（比如读取 100,000 行 CSV 数据到一个 OrderedDict 列表中去）， 那么你就得仔细权衡一下是否使用 OrderedDict 带来的好处要大过额外内存消耗的影响。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "foo 1\n",
      "bar 2\n",
      "spam 3\n",
      "grok 4\n",
      "--------------------\n",
      "foo 1\n",
      "bar 2\n",
      "spam 3\n",
      "grok 4\n"
     ]
    }
   ],
   "source": [
    "from collections import OrderedDict\n",
    "\n",
    "# 普通字典\n",
    "d1 = {}\n",
    "d1['foo'] = 1\n",
    "d1['bar'] = 2\n",
    "d1['spam'] = 3\n",
    "d1['grok'] = 4\n",
    "for key in d1:\n",
    "    print(key, d1[key])\n",
    "\n",
    "print('-'*20)\n",
    "# 有序字典\n",
    "d2 = OrderedDict()\n",
    "d2['foo'] = 1\n",
    "d2['bar'] = 2\n",
    "d2['spam'] = 3\n",
    "d2['grok'] = 4\n",
    "for key in d2:\n",
    "    print(key, d2[key])\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 8.字典的运算\n",
    "\n",
    "在数据字典中执行一些计算操作（比如求最小值、最大值、排序等等）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10.75, 'FB')"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "(612.78, 'AAPL')"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[(10.75, 'FB'),\n",
       " (37.2, 'HPQ'),\n",
       " (45.23, 'ACME'),\n",
       " (205.55, 'IBM'),\n",
       " (612.78, 'AAPL')]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(45.23, 'AAA')"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "(45.23, 'ZZZ')"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prices = {\n",
    "    'ACME': 45.23,\n",
    "    'AAPL': 612.78,\n",
    "    'IBM': 205.55,\n",
    "    'HPQ': 37.20,\n",
    "    'FB': 10.75\n",
    "}\n",
    "\n",
    "# zip() 函数创建的是一个只能访问一次的迭代器，第二次访问时，会报错\n",
    "# tmp = zip(prices.values(), prices.keys())\n",
    "# print(min(tmp)) # OK\n",
    "# print(max(tmp)) # ValueError: max() arg is an empty sequence\n",
    "\n",
    "# 查找最小和最大股票价格和股票值\n",
    "min(zip(prices.values(), prices.keys()))\n",
    "max(zip(prices.values(), prices.keys()))\n",
    "print('-'*20)\n",
    "\n",
    "# 可以使用 zip() 和 sorted() 函数来排列字典数据\n",
    "sorted(zip(prices.values(), prices.keys()))\n",
    "print('-'*20)\n",
    "\n",
    "# 需要注意的是在计算操作中使用到了 (值，键) 对。当多个实体拥有相同的值的时候，键会决定返回结果。\n",
    "# 比如，在执行 min() 和 max() 操作的时候，如果恰巧最小或最大值有重复的，那么拥有最小或最大键的实体会返回\n",
    "prices = { 'AAA' : 45.23, 'ZZZ': 45.23 }\n",
    "min(zip(prices.values(), prices.keys()))\n",
    "max(zip(prices.values(), prices.keys()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 9.查找两字典的相同点\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'x', 'y'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'w', 'x', 'y', 'z'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'z'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'w'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'w', 'z'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'x', 'y'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'w', 'x', 'y', 'z'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'z'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'w'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'w', 'z'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = {\n",
    "    'x' : 1,\n",
    "    'y' : 2,\n",
    "    'z' : 3\n",
    "}\n",
    "\n",
    "b = {\n",
    "    'w' : 10,\n",
    "    'x' : 11,\n",
    "    'y' : 2\n",
    "}\n",
    "\n",
    "a.keys() & b.keys()\n",
    "a.keys() | b.keys()\n",
    "a.keys() - b.keys()\n",
    "b.keys() - a.keys()\n",
    "b.keys() ^ a.keys()\n",
    "print('-'*20)\n",
    "set(a.keys()).intersection(b.keys())\n",
    "set(a.keys()).union(b.keys())\n",
    "set(a.keys()).difference(b.keys())\n",
    "set(b.keys()).difference(a.keys())\n",
    "set(a.keys()).symmetric_difference(b.keys())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 10.删除序列相同元素并保持顺序\n",
    "\n",
    "怎样在一个序列上面保持元素顺序的同时消除重复的值？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 5, 2, 1, 9, 1, 5, 10]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[1, 5, 2, 9, 10]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 序列上的值都是 hashable 类型，才起作用\n",
    "def dedupe11(items):\n",
    "    seen = set()\n",
    "    for item in items:\n",
    "        if item not in seen:\n",
    "            yield item\n",
    "            seen.add(item)\n",
    "\n",
    "# 序列上的值不是 hashable 类型，所以不起作用\n",
    "a = [1, 5, 2, 1, 9, 1, 5, 10]\n",
    "list(deque(a))\n",
    "\n",
    "\n",
    "def dedupe22(items, key=None):\n",
    "    seen = set()\n",
    "    for item in items:\n",
    "        val = item if key is None else key(item)\n",
    "        if val not in seen:\n",
    "            yield val\n",
    "            seen.add(val)\n",
    "\n",
    "list(dedupe22(a, lambda d: (d)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 11.命名切片\n",
    "\n",
    "代码中如果出现大量的硬编码下标会使得代码的可读性和可维护性大大降低。\n",
    "\n",
    "内置的 slice() 函数创建了一个切片对象。所有使用切片的地方都可以使用切片对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'100'"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'513.25'"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "######    0123456789012345678901234567890123456789012345678901234567890'\n",
    "record = '....................100 .......513.25 ..........'\n",
    "\n",
    "SHARES = slice(20, 23)\n",
    "PRICE = slice(31, 37)\n",
    "record[SHARES]\n",
    "record[PRICE]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[0, 1, 10, 11, 4, 5, 6]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[0, 1, 4, 5, 6]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "50"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(5, 10, 2)"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 W\n",
      "7 r\n",
      "9 d\n"
     ]
    }
   ],
   "source": [
    "items = [0, 1, 2, 3, 4, 5, 6]\n",
    "a = slice(2, 4)\n",
    "items[a]\n",
    "items[a] = [10,11]\n",
    "items\n",
    "del items[a]\n",
    "items\n",
    "\n",
    "print('-'*20)\n",
    "b = slice(5,50,2)\n",
    "b.start\n",
    "b.stop\n",
    "b.step\n",
    "\n",
    "print('-'*20)\n",
    "s = 'HelloWorld'\n",
    "b.indices(len(s))\n",
    "for i in range(*b.indices(len(s))):\n",
    "    print(i, s[i])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 12.序列中出现次数最多的元素\n",
    "\n",
    "collections.Counter 类就是专门为这类问题而设计的， 它甚至有一个有用的 most_common() 方法直接给了你答案。\n",
    "\n",
    "Counter 对象可以接受任意的由可哈希（hashable）元素构成的序列对象。 在底层实现上，一个 Counter 对象就是一个字典，将元素映射到它出现的次数上。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('eyes', 8),\n",
       " ('the', 5),\n",
       " ('look', 4),\n",
       " ('into', 3),\n",
       " ('my', 3),\n",
       " ('around', 2),\n",
       " ('not', 1),\n",
       " (\"don't\", 1),\n",
       " (\"you're\", 1),\n",
       " ('under', 1)]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[('eyes', 8), ('the', 5), ('look', 4)]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Counter({'look': 4,\n",
       "         'into': 3,\n",
       "         'my': 3,\n",
       "         'eyes': 8,\n",
       "         'the': 5,\n",
       "         'not': 1,\n",
       "         'around': 2,\n",
       "         \"don't\": 1,\n",
       "         \"you're\": 1,\n",
       "         'under': 1})"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "Counter({'why': 1,\n",
       "         'are': 1,\n",
       "         'you': 1,\n",
       "         'not': 1,\n",
       "         'looking': 1,\n",
       "         'in': 1,\n",
       "         'my': 1,\n",
       "         'eyes': 1})"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "Counter({'look': 4,\n",
       "         'into': 3,\n",
       "         'my': 4,\n",
       "         'eyes': 9,\n",
       "         'the': 5,\n",
       "         'not': 2,\n",
       "         'around': 2,\n",
       "         \"don't\": 1,\n",
       "         \"you're\": 1,\n",
       "         'under': 1,\n",
       "         'why': 1,\n",
       "         'are': 1,\n",
       "         'you': 1,\n",
       "         'looking': 1,\n",
       "         'in': 1})"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "Counter({'look': 4,\n",
       "         'into': 3,\n",
       "         'my': 2,\n",
       "         'eyes': 7,\n",
       "         'the': 5,\n",
       "         'around': 2,\n",
       "         \"don't\": 1,\n",
       "         \"you're\": 1,\n",
       "         'under': 1})"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from collections import Counter\n",
    "\n",
    "words = [\n",
    "    'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',\n",
    "    'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',\n",
    "    'eyes', \"don't\", 'look', 'around', 'the', 'eyes', 'look', 'into',\n",
    "    'my', 'eyes', \"you're\", 'under'\n",
    "]\n",
    "\n",
    "word_counts = Counter(words)\n",
    "word_counts.most_common()\n",
    "word_counts.most_common(3)\n",
    "\n",
    "print('-'*20)\n",
    "morewords = ['why','are','you','not','looking','in','my','eyes']\n",
    "\n",
    "a = Counter(words)\n",
    "b = Counter(morewords)\n",
    "\n",
    "a\n",
    "b\n",
    "a + b\n",
    "a - b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 13.通过某个或某几个字典字段排序一个字典列表\n",
    "\n",
    "通过使用 operator 模块的 itemgetter 函数，可以非常容易的排序这样的数据结构。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004},\n",
       " {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},\n",
       " {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},\n",
       " {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},\n",
       " {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},\n",
       " {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},\n",
       " {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},\n",
       " {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},\n",
       " {'fname': 'Big', 'lname': 'Jones', 'uid': 1004},\n",
       " {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},\n",
       " {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},\n",
       " {'fname': 'Big', 'lname': 'Jones', 'uid': 1004},\n",
       " {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from operator import itemgetter\n",
    "\n",
    "rows = [\n",
    "    {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},\n",
    "    {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},\n",
    "    {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},\n",
    "    {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}\n",
    "]\n",
    "\n",
    "rows_by_fname = sorted(rows, key=itemgetter('fname'))\n",
    "rows_by_fname\n",
    "\n",
    "rows_by_uid = sorted(rows, key=itemgetter('uid'))\n",
    "rows_by_uid\n",
    "\n",
    "rows_by_name = sorted(rows, key=itemgetter('lname', 'fname'))\n",
    "rows_by_name\n",
    "\n",
    "# itemgetter() 有时候也可以用 lambda 表达式代替\n",
    "# 但是，使用 itemgetter() 方式会运行的稍微快点。\n",
    "rows_by_lfname = sorted(rows, key=lambda r: (r['lname'],r['fname']))\n",
    "rows_by_lfname"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 14.排序不支持原生比较的对象\n",
    "\n",
    "可以使用 lambda 函数，也可以使用 operator.attrgetter() ，operator.attrgetter() 函数通常会运行的快点，并且还能同时允许多个字段进行比较。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[User(3), User(23), User(99)]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[User(3), User(23), User(99)]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from operator import attrgetter\n",
    "\n",
    "class User:\n",
    "    def __init__(self, user_id):\n",
    "        self.user_id = user_id\n",
    "\n",
    "    def __repr__(self):\n",
    "        return 'User({})'.format(self.user_id)\n",
    "\n",
    "users = [User(23), User(3), User(99)]\n",
    "\n",
    "sorted(users, key=lambda u: u.user_id)\n",
    "\n",
    "sorted(users, key=attrgetter('user_id'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 15.通过某个字段将记录分组\n",
    "\n",
    "有一个字典或者实例的序列，然后你想根据某个特定的字段比如 date 来分组迭代访问。\n",
    "\n",
    "itertools.groupby() 函数对于这样的数据分组操作非常实用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'address': '5412 N CLARK', 'date': '07/01/2012'},\n",
       " {'address': '4801 N BROADWAY', 'date': '07/01/2012'},\n",
       " {'address': '5800 E 58TH', 'date': '07/02/2012'},\n",
       " {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},\n",
       " {'address': '1060 W ADDISON', 'date': '07/02/2012'},\n",
       " {'address': '2122 N CLARK', 'date': '07/03/2012'},\n",
       " {'address': '5148 N CLARK', 'date': '07/04/2012'},\n",
       " {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}]"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "07/01/2012\n",
      "[{'address': '5412 N CLARK', 'date': '07/01/2012'}, {'address': '4801 N BROADWAY', 'date': '07/01/2012'}]\n",
      "07/02/2012\n",
      "[{'address': '5800 E 58TH', 'date': '07/02/2012'}, {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}, {'address': '1060 W ADDISON', 'date': '07/02/2012'}]\n",
      "07/03/2012\n",
      "[{'address': '2122 N CLARK', 'date': '07/03/2012'}]\n",
      "07/04/2012\n",
      "[{'address': '5148 N CLARK', 'date': '07/04/2012'}, {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}]\n"
     ]
    }
   ],
   "source": [
    "from itertools import groupby\n",
    "from operator import itemgetter\n",
    "\n",
    "rows = [\n",
    "    {'address': '5412 N CLARK', 'date': '07/01/2012'},\n",
    "    {'address': '5148 N CLARK', 'date': '07/04/2012'},\n",
    "    {'address': '5800 E 58TH', 'date': '07/02/2012'},\n",
    "    {'address': '2122 N CLARK', 'date': '07/03/2012'},\n",
    "    {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},\n",
    "    {'address': '1060 W ADDISON', 'date': '07/02/2012'},\n",
    "    {'address': '4801 N BROADWAY', 'date': '07/01/2012'},\n",
    "    {'address': '1039 W GRANVILLE', 'date': '07/04/2012'},\n",
    "]\n",
    "\n",
    "# 先按date进行排序\n",
    "# 因为 groupby() 仅仅检查连续的元素，如果事先并没有排序完成的话，分组函数将得不到想要的结果。\n",
    "rows.sort(key=itemgetter('date'))\n",
    "rows\n",
    "\n",
    "for date, items in groupby(rows, key=itemgetter('date')):\n",
    "    print(date)\n",
    "    print(list(items))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 16.过滤序列元素\n",
    "\n",
    "你有一个数据序列，想利用一些规则从中提取出需要的值或者是缩短序列。\n",
    "\n",
    "方法：\n",
    "- 列表推导\n",
    "- 生成器表达式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 4, 10, 2, 3]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "<generator object <genexpr> at 0x7f7f1819b970>"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['1', '2', '-3', '4', '5']"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mylist = [1, 4, -5, 10, -7, 2, 3, -1]\n",
    "\n",
    "# 列表推导\n",
    "a = [n for n in mylist if n > 0]\n",
    "a\n",
    "\n",
    "# 生成器表达式\n",
    "b = (n for n in mylist if n > 0)\n",
    "b\n",
    "\n",
    "# 内建的 filter() 函数\n",
    "values = ['1', '2', '-3', '-', '4', 'N/A', '5']\n",
    "def is_int(val):\n",
    "    try:\n",
    "        x = int(val)\n",
    "        return True\n",
    "    except:\n",
    "        return False\n",
    "    \n",
    "c = list(filter(is_int, values))\n",
    "c"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 17.从字典中提取子集\n",
    "\n",
    "你想构造一个字典，它是另外一个字典的子集。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'AAPL': 612.78, 'IBM': 205.55}"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用字典推导\n",
    "prices = {\n",
    "    'ACME': 45.23,\n",
    "    'AAPL': 612.78,\n",
    "    'IBM': 205.55,\n",
    "    'HPQ': 37.20,\n",
    "    'FB': 10.75\n",
    "}\n",
    "\n",
    "p1 = {key:val for key, val in prices.items() if val > 200}\n",
    "p1\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 18.映射名称到序列元素\n",
    "\n",
    "你有一段通过下标访问列表或者元组中元素的代码，但是这样有时候会使得你的代码难以阅读， 于是你想通过名称来访问元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Subscriber(addr='jonesy@example.com', joined='2012-10-19')"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'jonesy@example.com'"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "'2012-10-19'"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from collections import namedtuple\n",
    "\n",
    "Subscriber = namedtuple('Subscriber', ['addr', 'joined'])\n",
    "sub = Subscriber('jonesy@example.com', '2012-10-19')\n",
    "sub\n",
    "sub.addr\n",
    "sub.joined\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Stock(name='ACME', shares=100, price=123.45)"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "Stock(name='ACME', shares=100, price=123.45)"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "Stock(name='ACME', shares=75, price=123.45)"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 不像字典那样，一个命名元组是不可更改的。\n",
    "# 如果你真的需要改变属性的值，那么可以使用命名元组实例的 _replace() 方法， 它会创建一个全新的命名元组并将对应的字段用新的值取代。\n",
    "Stock = namedtuple('Stock', ['name', 'shares', 'price'])\n",
    "s = Stock('ACME', 100, 123.45)\n",
    "s\n",
    "s2 = s._replace(shares=75)\n",
    "s\n",
    "s2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 19.转换并同时计算数据\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用一个生成器表达式参数\n",
    "nums = [1, 2, 3, 4, 5]\n",
    "s = sum(x*x for x in nums)\n",
    "s\n",
    "\n",
    "portfolio = [\n",
    "    {'name':'GOOG', 'shares': 50},\n",
    "    {'name':'YHOO', 'shares': 75},\n",
    "    {'name':'AOL', 'shares': 20},\n",
    "    {'name':'SCOX', 'shares': 65}\n",
    "]\n",
    "min_shares = min(x['shares'] for x in portfolio)\n",
    "min_shares"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 20.合并多个字典或映射\n",
    "\n",
    "现在有多个字典或者映射，你想将它们从逻辑上合并为一个单一的映射后执行某些操作， 比如查找值或者检查某些键是否存在。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "KeysView(ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4}))"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['y', 'z', 'x']"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "ValuesView(ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4}))"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "[2, 3, 1]"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "ChainMap({'z': 10, 'w': 40}, {'y': 2, 'z': 4})"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "{'z': 10, 'w': 40}"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用 collections 模块中的 ChainMap 类\n",
    "a = {'x': 1, 'z': 3 }\n",
    "b = {'y': 2, 'z': 4 }\n",
    "\n",
    "from collections import  ChainMap\n",
    "c = ChainMap(a, b)\n",
    "\n",
    "c['x']\n",
    "c['y']\n",
    "c['z']\n",
    "\n",
    "len(c)\n",
    "c.keys()\n",
    "list(c.keys())\n",
    "c.values()\n",
    "list(c.values())\n",
    "\n",
    "# 对于字典的更新或删除操作总是影响的是列表中第一个字典。\n",
    "c['z'] = 10\n",
    "c['w']= 40\n",
    "del c['x']\n",
    "c\n",
    "a\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
